/**
 * main.cpp 
 * Autor: Danilo S. Carvalho	DRE: 107390588
 * 		  Taísa L. Martins		DRE: 107362828
 * 
 */
#include <cstdlib>
#include <iostream>
#include "TinyThread/tinythread.h"
#include "simulador.h"

using namespace SimuladorAD;

int cont_thread; // Contador de threads.

void executar_simulador(void* args) {
	
    Configuracao conf;
    tthread::mutex mtx;

	// Região crítica para leitura da entrada padrão.
	// Apenas uma thread pode ler a entrada por vez.
    mtx.lock();
    EntradaPadrao::ler_config(conf);
    mtx.unlock();

	// Se a semente escolhida for zero gera uma automaticamente de forma aleatória.
    if (conf.semente_chegada == 0)
        conf.semente_chegada = Rng::gerar_semente();
    if (conf.semente_servico == 0)
        conf.semente_servico = Rng::gerar_semente();

    
    Simulador sim(conf);
    
    sim.saida_graf = new SaidaGrafico(2);
    sim.saida_std = new SaidaPadrao();
    sim.executa();  // Roda a simulação.

    std::stringstream prefx;
    
    // Finalmente escreve as saídas em arquivos.
    if (conf.modo == ModoBatch)
        prefx << "batch_dados" << (int)args << "__ro" << conf.taxa_chegada * 2;
    else if (conf.modo == ModoReplicativo)
        prefx << "repl_dados" << (int)args << "__ro" << conf.taxa_chegada * 2;
    else
        prefx << "trans_dados" << (int)args << "__ro" << conf.taxa_chegada * 2;

    sim.saida_graf->escrever_arquivos("relatorio/dados_plot/", prefx.str().c_str());
    
    prefx.str("");
    prefx << "resultados_" << (int)args;
    std::string prefx_res = prefx.str();
    
    prefx.str("");
    prefx << "mensagens_" << (int)args;
    std::string prefx_msg = prefx.str();

    sim.saida_std->escrever_arquivos("./", prefx_res, prefx_msg);
    
    // Libera os recursos alocados para E/S.
    delete sim.saida_graf;
    delete sim.saida_std;
}

/** Executa uma simulação por thread. */
void executar_multi(int num_threads) {
	
    for (int cont_thread = 0; cont_thread < num_threads; cont_thread++) {
		// Dispara cada thread
        tthread::thread thread_sim(executar_simulador, (void*)cont_thread);
        
        // Aguarda todas terminarem para acabar.
        thread_sim.join();
    }
}

int main(int argc, char *argv[]) {    
	
    if (argc > 1)
        executar_multi(atoi(argv[1])); 	//executar multi-thread
    else
        executar_simulador(NULL);		//executar serialmente


    return 0;
}

